package com.jueban.serviceImpl;

import com.jueban.Dto.ApplyRewardDto;
import com.jueban.Dto.ApplyRewardQueryDto;
import com.jueban.Dto.SuggestAuditDto;
import com.jueban.Vo.ApplyRewardVo;
import com.jueban.Vo.ResultVo;
import com.jueban.model.*;
import com.jueban.model.user.User;
import com.jueban.repository.ApplyOfIPRepository;
import com.jueban.repository.ApplyRewardRepository;
import com.jueban.repository.RewardPriceRepository;
import com.jueban.service.ApplyRewardService;
import com.jueban.service.UserService;
import com.jueban.util.Enum.JobType;
import com.jueban.util.Enum.UserType;
import com.jueban.util.Messages;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;


@Service
public class ApplyRewardServiceImpl implements ApplyRewardService {

    private final ApplyOfIPRepository applyOfIPRepository;

    private final UserService userService;

    private final RewardPriceRepository rewardPriceRepository;

    private final ApplyRewardRepository applyRewardRepository;

    @Autowired
    public ApplyRewardServiceImpl(ApplyOfIPRepository applyOfIPRepository, UserService userService, RewardPriceRepository rewardPriceRepository, ApplyRewardRepository applyRewardRepository) {
        this.applyOfIPRepository = applyOfIPRepository;
        this.userService = userService;
        this.rewardPriceRepository = rewardPriceRepository;
        this.applyRewardRepository = applyRewardRepository;
    }

    /*------------------------------------------CREATE--------------------------------------------------*/


    /**
     * 申请奖励
     *
     * @param applyRewardDto 奖励申请资料
     * @return 操作结果
     */
    @Override
    @PreAuthorize("isAuthenticated()")
    public ResultVo applyReward(ApplyRewardDto applyRewardDto) {
        ApplyOfIP applyOfIP = applyOfIPRepository.findOne(applyRewardDto.getApplyOfIPId());
        User user = userService.getUser();

        //判断该User能否通过这个applyOfIP申请奖励,若不能则返回错误信息
        ResultVo resultVo = isGoodApplyReward(applyOfIP, user);
        if (resultVo != null) {
            return resultVo;
        } else {
            resultVo = new ResultVo();
        }

        //创建奖励申请并保存和返回操作结果
        ApplyReward applyReward = new ApplyReward();
        applyReward.setApplyOfIP(applyOfIP);
        applyReward.setUser(user);
        applyReward.setSate(new RewardState());
        int reward = rewardPriceRepository.findByApplyOfIPType(
                applyOfIP.getApplyInfo().getApplyType().toString()).getPrice();
        applyReward.setReward(reward);
        applyRewardRepository.save(applyReward);
        resultVo.setMessages(Messages.APPLY_REWARD_SUCCEED);
        resultVo.setSucceeded();
        return resultVo;
    }

    /**
     * 判断该User能否通过这个applyOfIP申请奖励
     *
     * @param applyOfIP 知识产权申请
     * @param user      用户
     * @return 诺不能返回包含错误信息的ResultVo，若能返回null
     */
    private ResultVo isGoodApplyReward(ApplyOfIP applyOfIP, User user) {

        ResultVo resultVo = new ResultVo();

        //判断操作人和查询的知识产权申请是否为空，若为空返回错误信息
        if (user == null || applyOfIP == null) {
            resultVo.setFailed();
            if (user == null) resultVo.setMessages(Messages.IS_NO_LOGIN);
            else resultVo.setMessages(Messages.NO_APPLY_OF_IP);
            return resultVo;
        }

        //若奖励申请的知识产权的申请人不是操作人则返回错误信息
        if (!applyOfIP.getApplicant().getId().equals(user.getId())) {
            resultVo.setFailed();
            resultVo.setMessages(Messages.THE_APPLY_NO_BELONG_SELF);
            return resultVo;
        }

        //若奖励申请的知识产权未审核完成则返回错误信息
        State state = applyOfIP.getState();
        if (state.getHashCode() != State.FULL_AUDITED_HASHCODE) {
            resultVo.setFailed();
            resultVo.setMessages(Messages.APPLY_OF_IP_IS_NOT_AUDITED);
            return resultVo;
        }

        //若知识产权已申请过奖励则返回错误信息
        if (applyRewardRepository.findByApplyOfIP(applyOfIP) != null) {
            resultVo.setFailed();
            resultVo.setMessages(Messages.APPLY_REWARD_ALREADY_EXIT);
            return resultVo;
        }

        return null;

    }


    /*-------------------------------------------READ--------------------------------------------------*/


    /**
     * 根据id获取奖励申请详细信息
     *
     * @param id id
     * @return 申请奖励的详细信息
     */
    @Override
    @PreAuthorize("isAuthenticated()")
    public ApplyRewardVo getApplyReward(Integer id) {
        ApplyRewardVo applyRewardVo = new ApplyRewardVo();
        ApplyReward applyReward = applyRewardRepository.findOne(id);
        if (applyReward == null) {
            applyRewardVo.setFailed();
            applyRewardVo.setMessages(Messages.HAS_NO_ID_IN_APPLY_REWARD);
        }
        applyRewardVo.setProperties(applyReward);
        applyRewardVo.setSucceeded();
        applyRewardVo.setMessages(Messages.APPLY_REWARD_FIND_SUCCEED);
        return applyRewardVo;
    }


    @Override
    @PreAuthorize("isAuthenticated()")
    public Page<ApplyReward> findSelfApplyReward
            (ApplyRewardQueryDto applyRewardQueryDto) {
        User user = userService.getUser();
        Pageable pageable = new PageRequest(applyRewardQueryDto.getOffset()
                , applyRewardQueryDto.getPageSize());
        return applyRewardRepository.findApplyRewardsByUser(pageable, user);
    }

    //admin
    @Override
    @PreAuthorize("hasRole('ROLE_admin')")
    public Page<ApplyReward> findAdminApplyRewards(ApplyRewardQueryDto applyRewardQueryDto) {
        RewardState rewardState = applyRewardQueryDto.getRewardState();
        Page<ApplyReward> result;
        Pageable pageable = new PageRequest(applyRewardQueryDto.getOffset()
                , applyRewardQueryDto.getPageSize());
        if (rewardState == null) {
            result = applyRewardRepository.findApplyRewards(pageable
                    , applyRewardQueryDto.getDepartment(), applyRewardQueryDto.getApplyName()
                    , applyRewardQueryDto.getApplicantName());
        } else {
            result = applyRewardRepository.findApplyRewardsWithState(pageable, rewardState.hashCode()
                    , applyRewardQueryDto.getDepartment(), applyRewardQueryDto.getApplyName()
                    , applyRewardQueryDto.getApplicantName());
        }
        return result;
    }


    // departmentHead chargeOfIP leader
    @Override
    @PreAuthorize("hasRole('ROLE_admin') or hasRole('ROLE_departmentHead') " +
            "or hasRole('ROLE_chargeOfIP')" +
            "or hasRole('ROLE_leader') or hasRole('ROLE_personnel')")
    public Page<ApplyReward> findTeacherApplyRewards(ApplyRewardQueryDto applyRewardQueryDto) {
        User user = userService.getUser();
        RewardState state = getRewardState(user);
        Pageable pageable = new PageRequest(applyRewardQueryDto.getOffset()
                , applyRewardQueryDto.getPageSize());
        if (state == null) {
            return applyRewardRepository.findApplyRewardsByUser(pageable, user);
        } else {
            return applyRewardRepository.findApplyRewardsWithState(pageable, state.hashCode()
                    , user.getDepartment(), applyRewardQueryDto.getApplyName()
                    , applyRewardQueryDto.getApplicantName());
        }
    }

    /**
     * 根据操作人对职位返回对应的RewardState，该返回结果用来查询相同状态的奖励申请
     *
     * @param user 操作人(应为老师)
     * @return 查询用状态
     */
    private RewardState getRewardState(User user) {
        RewardState rewardState = new RewardState();

        if (user.getUserType().equals(UserType.teacher)) {
            switch (user.getJobType()) {
                case leader:
                    rewardState.setIsPersonnelAuditedPass(true);
                case personnel:
                    rewardState.setIsAcademicAuditedPass(true);
                case chargeOfIP:
                    rewardState.setIsDepartmentAuditPass(true);
                case departmentHead:
                    break;
                default:
                    return null;
            }
            return rewardState;
        } else {
            return null;
        }
    }

    /*----------------------------------------------UPDATE-----------------------------------------------*/

    // departmentHead chargeOfIP leader

    /**
     * 审核奖励申请
     *
     * @param suggestAuditDto 要审核的奖励信息
     * @return 操作结果
     */
    @Override
    @PreAuthorize("hasRole('ROLE_admin') or hasRole('ROLE_departmentHead') " +
            "or hasRole('ROLE_chargeOfIP') or hasRole('ROLE_manager') " +
            "or hasRole('ROLE_leader') or hasRole('ROLE_personnel')")
    public ResultVo auditReward(SuggestAuditDto suggestAuditDto) {
        //获取操作人和奖励申请
        User user = userService.getUser();
        ApplyReward applyReward = applyRewardRepository.findOne(suggestAuditDto.getApplyId());
        ResultVo resultVo = new ResultVo();

        //若操作人或奖励申请查询不到则返回错误信息
        if (user == null || applyReward == null) {
            resultVo.setFailed();
            if (user == null) resultVo.setMessages(Messages.IS_NO_LOGIN);
            else resultVo.setMessages(Messages.HAS_NO_ID_IN_APPLY_REWARD);
            return resultVo;
        }

        //根据操作人的相应职位对奖励申请进行审核并返回操作结果
        if (setRewardAudit(suggestAuditDto, applyReward, user)) {
            applyRewardRepository.save(applyReward);
            resultVo.setSucceeded();
            resultVo.setMessages(Messages.APPLY_REWARD_AUDIT_SUCCEED);
        } else {
            resultVo.setFailed();
            resultVo.setMessages(Messages.CANNOT_AUDIT_APPLY_REWARD);
        }
        return resultVo;
    }

    // departmentHead chargeOfIP leader   部门部长，科研处处长，人事处，院领导

    /**
     * 根据操作人的相应职位对奖励申请进行审核
     *
     * @param suggestAuditDto 审核结果
     * @param applyReward     要审核对申请
     * @param user            审核人
     * @return 是否能审核
     */
    @PreAuthorize("hasRole('ROLE_admin') or hasRole('ROLE_departmentHead') " +
            "or hasRole('ROLE_chargeOfIP') or hasRole('ROLE_manager') " +
            "or hasRole('ROLE_leader') or hasRole('ROLE_personnel')")
    private boolean setRewardAudit
    (SuggestAuditDto suggestAuditDto, ApplyReward applyReward, User user) {

        //创建一个建议
        Suggest suggest = Suggest.makeSuggest(suggestAuditDto.getSuggest(), user);

        //若操作人为老师则进行审核并返回操作结果
        if (user.getUserType().equals(UserType.teacher)) {
            return applyReward.auditByJob(user.getJobType(), suggest, suggestAuditDto.getIsPass());
        } else {
            //TODO 增加管理员审核
            return applyReward.auditByJob(JobType.valueOf(suggestAuditDto.getAuditType()),suggest,suggestAuditDto.getIsPass());
        }
    }


}


/*
* //判断操作人和查询的知识产权申请是否为空，若为空返回错误信息
        if (user == null || applyOfIP == null) {
            resultVo.setFailed();
            if (user == null) resultVo.setMessages(Messages.IS_NO_LOGIN);
            else resultVo.setMessages(Messages.NO_APPLY_OF_IP);
            return resultVo;
        }

        //若奖励申请的知识产权的申请人不是操作人则返回错误信息
        if (!applyOfIP.getApplicant().getId().equals(user.getId())) {
            resultVo.setFailed();
            resultVo.setMessages(Messages.THE_APPLY_NO_BELONG_SELF);
            return resultVo;
        }

        //若奖励申请的知识产权未审核完成则返回错误信息
        if (applyOfIP.getState().hashCode() != getAuditedState().hashCode()) {
            resultVo.setFailed();
            resultVo.setMessages(Messages.APPLY_OF_IP_IS_NOT_AUDITED);
            return resultVo;
        }

        //若知识产权已申请过奖励则返回错误信息
        if (applyRewardRepository.findByApplyOfIP(applyOfIP) != null) {
            resultVo.setFailed();
            resultVo.setMessages(Messages.APPLY_REWARD_ALREADY_EXIT);
            return resultVo;
        }
* */

/*
* Teacher teacher = new Teacher();
        teacher.setUserType(UserType.teacher);
        teacher.setType(JobType.departmentHead);
        String type = user.getType();
        RewardState rewardState = applyReward.getSate();
        if (type.equals(teacher.getType())) {
            applyReward.setDepartmentSuggest(suggest);
            rewardState.setDepartmentAuditPass(suggestAuditDto.getIsPass());
            return true;
        }
        teacher.setType(JobType.chargeOfIP);
        if (type.equals(teacher.getType())) {
            applyReward.setAcademicSuggest(suggest);
            rewardState.setAcademicAuditedPass(suggestAuditDto.getIsPass());
            return true;
        }
        teacher.setType(JobType.leader);
        if (type.equals(teacher.getType())) {
            applyReward.setLeaderSuggest(suggest);
            rewardState.setLeaderAuditedPass(suggestAuditDto.getIsPass());
            return true;
        }
        return false;*/

/*
* Teacher teacher = new Teacher();
        teacher.setUserType(UserType.teacher);
        teacher.setType(JobType.departmentHead);
        String job = user.getType();
        if (job.equals(teacher.getType())) {
            return rewardState;
        }
        teacher.setType(JobType.chargeOfIP);

        if (job.equals(teacher.getType())) {
            rewardState.setDepartmentAuditPass(true);
            return rewardState;
        }
        teacher.setType(JobType.leader);

        if (job.equals(teacher.getType())) {
            rewardState.setDepartmentAuditPass(true);
            rewardState.setAcademicAuditedPass(true);
            return rewardState;
        }
        return null;*/

/*
*  private State getAuditedState() {
        State state = new State();
        state.setIsDepartmentAuditedPass(true);
        state.setIsManagerAuditedPass(true);
        state.setIsAcademicAuditedPass(true);
        state.setIsEnterProxyForm(true);
        state.setIsAuthorized(true);
        return state;
    }
* */